package com.wingsoft.homeFlow.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wingsoft.common.core.domain.model.LoginUser;
import com.wingsoft.common.enums.SwitchEnum;
import com.wingsoft.common.exception.ServiceException;
import com.wingsoft.common.utils.DateUtil;
import com.wingsoft.common.utils.SecurityUtils;
import com.wingsoft.common.utils.bean.BeanConvertUtils;
import com.wingsoft.homeFlow.bo.*;
import com.wingsoft.homeFlow.entity.HomeFlowTask;
import com.wingsoft.homeFlow.entity.HomeFlowTaskLog;
import com.wingsoft.homeFlow.entity.HomeFlowTaskStep;
import com.wingsoft.homeFlow.entity.HomeFlowTaskVar;
import com.wingsoft.homeFlow.mapper.HomeFlowTaskMapper;
import com.wingsoft.homeFlow.service.HomeFlowTaskLogService;
import com.wingsoft.homeFlow.service.HomeFlowTaskService;
import com.wingsoft.homeFlow.service.HomeFlowTaskStepService;
import com.wingsoft.homeFlow.service.HomeFlowTaskVarService;
import com.wingsoft.homeFlow.utils.VelocityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Wingsoft
 * @description 针对表【HOME_FLOW_TASK(流水线任务)】的数据库操作Service实现
 * @createDate 2025-06-03 13:14:30
 */

@Slf4j
@Service
public class HomeFlowTaskServiceImpl extends ServiceImpl<HomeFlowTaskMapper, HomeFlowTask> implements HomeFlowTaskService {
    @Autowired
    private HomeFlowTaskStepService homeFlowTaskStepService;
    @Autowired
    private HomeFlowTaskVarService homeFlowTaskVarService;
    @Autowired
    private HomeFlowTaskLogService homeFlowTaskLogService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Transactional
    @Override
    public HomeFlowTaskVo add(HomeFlowTaskAddBo homeFlowTaskAddBo) {
        String companyCode = homeFlowTaskAddBo.getCompanyCode();
        if (StringUtils.isBlank(companyCode)) {
            homeFlowTaskAddBo.setCompanyCode("*");
        }
        String hospitalCode = homeFlowTaskAddBo.getHospitalCode();
        if (StringUtils.isBlank(hospitalCode)) {
            homeFlowTaskAddBo.setHospitalCode("*");
        }
        String taskCode = homeFlowTaskAddBo.getTaskCode();
        if (StringUtils.isBlank(taskCode)) {
            throw new ServiceException("任务编码 不能为空");
        }
        String taskName = homeFlowTaskAddBo.getTaskName();
        if (StringUtils.isBlank(taskName)) {
            throw new ServiceException("任务名称 不能为空");
        }
        Integer showIndex = homeFlowTaskAddBo.getShowIndex();
        if (Objects.isNull(showIndex)) {
            homeFlowTaskAddBo.setShowIndex(0);
        }
        Integer isUsed = homeFlowTaskAddBo.getIsUsed();
        if (Objects.isNull(isUsed)) {
            homeFlowTaskAddBo.setIsUsed(SwitchEnum.TRUE.getCode());
        } else {
            SwitchEnum.getEnumByCode(isUsed);
        }
        Long userId = SecurityUtils.getUserId();
        Date date = new Date();
        HomeFlowTask homeFlowTask = BeanConvertUtils.convert(homeFlowTaskAddBo, HomeFlowTask.class, (s, t) -> {
            t.setCreateUserId(userId);
            t.setCreateTime(date);
            t.setUpdateUserId(userId);
            t.setUpdateTime(date);
        });
        if (!this.save(homeFlowTask)) {
            throw new ServiceException("添加失败");
        }
        return BeanConvertUtils.convert(homeFlowTask, HomeFlowTaskVo.class);
    }

    @Transactional
    @Override
    public void delById(String id) {
        HomeFlowTask homeFlowTask = this.getById(id);
        if (Objects.isNull(homeFlowTask)) {
            throw new ServiceException("任务不存在，id=" + id);
        }
        if (!this.removeById(id)) {
            throw new ServiceException("删除失败");
        }
        homeFlowTaskStepService.remove(new LambdaQueryWrapper<HomeFlowTaskStep>() {{
            eq(HomeFlowTaskStep::getTaskCode, homeFlowTask.getTaskCode());
        }});
        homeFlowTaskVarService.remove(new LambdaQueryWrapper<HomeFlowTaskVar>() {{
            eq(HomeFlowTaskVar::getTaskCode, homeFlowTask.getTaskCode());
        }});
        new Thread(() -> {
            while (true) {
                Page<HomeFlowTaskLog> page = homeFlowTaskLogService.page(new Page<>(1, 1000), new LambdaQueryWrapper<HomeFlowTaskLog>() {{
                    select(HomeFlowTaskLog::getId);
                    eq(HomeFlowTaskLog::getTaskCode, homeFlowTask.getTaskCode());
                }});
                List<HomeFlowTaskLog> records = page.getRecords();
                if (CollectionUtils.isNotEmpty(records)) {
                    homeFlowTaskLogService.removeByIds(records.stream().map(HomeFlowTaskLog::getId).collect(Collectors.toList()));
                } else {
                    break;
                }
            }
        }).start();
    }

    @Transactional
    @Override
    public void uptById(HomeFlowTaskUptBo homeFlowTaskUptBo) {
        String id = homeFlowTaskUptBo.getId();
        if (StringUtils.isBlank(id)) {
            throw new ServiceException("ID 不能为空");
        }
        HomeFlowTask homeFlowTask = this.getById(id);
        String companyCode = homeFlowTaskUptBo.getCompanyCode();
        if (StringUtils.isBlank(companyCode)) {
            homeFlowTaskUptBo.setCompanyCode("*");
        }
        String hospitalCode = homeFlowTaskUptBo.getHospitalCode();
        if (StringUtils.isBlank(hospitalCode)) {
            homeFlowTaskUptBo.setHospitalCode("*");
        }
        String taskCode = homeFlowTaskUptBo.getTaskCode();
        if (StringUtils.isBlank(taskCode)) {
            throw new ServiceException("任务编码 不能为空");
        }
        String taskName = homeFlowTaskUptBo.getTaskName();
        if (StringUtils.isBlank(taskName)) {
            throw new ServiceException("任务名称 不能为空");
        } else {
            List<HomeFlowTask> list = this.list(new LambdaQueryWrapper<HomeFlowTask>() {{
                eq(HomeFlowTask::getTaskCode, taskCode);
                ne(HomeFlowTask::getId, id);
            }});
            if (CollectionUtils.isNotEmpty(list)) {
                throw new ServiceException("任务编码 已存在");
            }
        }
        Integer showIndex = homeFlowTaskUptBo.getShowIndex();
        if (Objects.isNull(showIndex)) {
            homeFlowTaskUptBo.setShowIndex(0);
        }
        Integer isUsed = homeFlowTaskUptBo.getIsUsed();
        if (Objects.nonNull(isUsed)) {
            SwitchEnum.getEnumByCode(isUsed);
        }
        Long userId = SecurityUtils.getUserId();
        if (!this.updateById(BeanConvertUtils.convert(homeFlowTaskUptBo, HomeFlowTask.class, (s, t) -> {
            t.setUpdateUserId(userId);
            t.setUpdateTime(new Date());
        }))) {
            throw new ServiceException("修改失败");
        }
        if (!Objects.equals(homeFlowTask.getTaskCode(), taskCode)) {
            homeFlowTaskStepService.update(new LambdaUpdateWrapper<HomeFlowTaskStep>() {{
                eq(HomeFlowTaskStep::getTaskCode, homeFlowTask.getTaskCode());
                set(HomeFlowTaskStep::getTaskCode, taskCode);
            }});
            homeFlowTaskVarService.update(new LambdaUpdateWrapper<HomeFlowTaskVar>() {{
                eq(HomeFlowTaskVar::getTaskCode, homeFlowTask.getTaskCode());
                set(HomeFlowTaskVar::getTaskCode, taskCode);
            }});
        }
    }

    @Transactional
    @Override
    public void uptStatusById(HomeFlowTaskUptBo homeFlowTaskUptBo) {
        String id = homeFlowTaskUptBo.getId();
        if (StringUtils.isBlank(id)) {
            throw new ServiceException("ID 不能为空");
        }
        Integer isUsed = homeFlowTaskUptBo.getIsUsed();
        if (Objects.isNull(isUsed)) {
            throw new ServiceException("是否启用 不能为空");
        } else {
            SwitchEnum.getEnumByCode(isUsed);
        }
        Long userId = SecurityUtils.getUserId();
        if (!this.updateById(new HomeFlowTask() {{
            setId(id);
            setIsUsed(isUsed);
            setUpdateUserId(userId);
            setUpdateTime(new Date());
        }})) {
            throw new ServiceException("修改失败");
        }
    }

    @Override
    public Page<HomeFlowTaskVo> page(HomeFlowTaskQo homeFlowTaskQo) {
        String id = homeFlowTaskQo.getId();
        String companyCode = homeFlowTaskQo.getCompanyCode();
        String hospitalCode = homeFlowTaskQo.getHospitalCode();
        String taskCode = homeFlowTaskQo.getTaskCode();
        String taskName = homeFlowTaskQo.getTaskName();
        Integer taskDirectionType = homeFlowTaskQo.getTaskDirectionType();
        Integer isUsed = homeFlowTaskQo.getIsUsed();
        int pageNum = homeFlowTaskQo.getPageNum();
        int pageSize = homeFlowTaskQo.getPageSize();

        Page<HomeFlowTask> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<HomeFlowTask> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(id)) {
            queryWrapper.eq(HomeFlowTask::getId, id);
        }
        if (StringUtils.isNotBlank(companyCode)) {
            queryWrapper.eq(HomeFlowTask::getCompanyCode, companyCode);
        }
        if (StringUtils.isNotBlank(hospitalCode)) {
            queryWrapper.eq(HomeFlowTask::getHospitalCode, hospitalCode);
        }
        if (StringUtils.isNotBlank(taskCode)) {
            queryWrapper.eq(HomeFlowTask::getTaskCode, taskCode);
        }
        if (StringUtils.isNotBlank(taskName)) {
            queryWrapper.eq(HomeFlowTask::getTaskName, taskName.trim());
        }
        if (Objects.nonNull(taskDirectionType)) {
            HomeFlowTaskBo.TaskDirectionTypeEnum taskDirectionTypeEnum = HomeFlowTaskBo.TaskDirectionTypeEnum.getEnumByCode(taskDirectionType);
            queryWrapper.eq(HomeFlowTask::getTaskDirectionType, taskDirectionTypeEnum.getCode());
        }
        if (Objects.nonNull(isUsed)) {
            queryWrapper.eq(HomeFlowTask::getIsUsed, isUsed);
        }
        queryWrapper.orderByAsc(HomeFlowTask::getShowIndex);
        queryWrapper.orderByDesc(HomeFlowTask::getCreateTime);
        queryWrapper.orderByDesc(HomeFlowTask::getId);
        page.setOptimizeCountSql(false);
        Page<HomeFlowTask> homeFlowTaskPage = this.page(page, queryWrapper);
        return BeanConvertUtils.convert(homeFlowTaskPage, Page.class, (s, t) -> {
            t.setRecords(BeanConvertUtils.convertList(s.getRecords(), HomeFlowTaskVo.class));
        });
    }

    @Override
    public HomeFlowTaskVo getVoById(String id) {
        HomeFlowTaskVo homeFlowTaskVo = BeanConvertUtils.convert(
                this.getOne(new LambdaQueryWrapper<HomeFlowTask>() {{
                    eq(HomeFlowTask::getId, id);
                }}),
                HomeFlowTaskVo.class);
        if (Objects.isNull(homeFlowTaskVo)) {
            throw new ServiceException("任务不存在，id：" + id);
        }
        return homeFlowTaskVo;
    }

    @Override
    public HomeFlowTask getByTaskCode(String taskCode) {
        return this.getOne(new LambdaQueryWrapper<HomeFlowTask>() {{
            eq(HomeFlowTask::getTaskCode, taskCode);
        }});
    }

    @Override
    public HomeFlowTaskExecVo execTask(HomeFlowTaskExecBo homeFlowTaskExecBo) {
        Object result = null;
        String redisKeyFlowExecTask = homeFlowTaskStepService.getRedisKeyFlowExecTask(homeFlowTaskExecBo.getTaskCode());
        try {
            redisTemplate.delete(redisKeyFlowExecTask);
            result = this.doExecTask(homeFlowTaskExecBo);
        } catch (Exception e) {
            log.error("任务执行失败", e);
        }
        if (homeFlowTaskExecBo.getTaskLog().getSuccessFlag()) {
            redisTemplate.delete(redisKeyFlowExecTask);
        }
        HomeFlowTaskExecTaskLogVo taskLog = homeFlowTaskExecBo.getTaskLog();
        HomeFlowTaskExecVo homeFlowTaskExecVo = new HomeFlowTaskExecVo();
        homeFlowTaskExecVo.setResult(result);
        homeFlowTaskExecVo.setTaskLog(taskLog);
        return homeFlowTaskExecVo;
    }

    @Override
    public HomeFlowTaskExecTaskLogVo getExecTaskLog(String taskCode) {
        String redisKeyFlowExecTask = homeFlowTaskStepService.getRedisKeyFlowExecTask(taskCode);
        String str = redisTemplate.opsForValue().get(redisKeyFlowExecTask);
        if (StringUtils.isBlank(str)) {
            return null;
        } else {
            return JSONUtil.toBean(str, HomeFlowTaskExecTaskLogVo.class);
        }
    }

    @Override
    public void updateTaskDirectionTypeByTaskCode(String taskCode, Integer taskDirectionType) {
        if (!this.update(new LambdaUpdateWrapper<HomeFlowTask>() {{
            eq(HomeFlowTask::getTaskCode, taskCode);
            set(HomeFlowTask::getTaskDirectionType, taskDirectionType);
        }})) {
            throw new ServiceException("修改失败");
        }
    }

    private Object doExecTask(HomeFlowTaskExecBo homeFlowTaskExecBo) {
        long taskStartTime = System.currentTimeMillis();
        String taskCode = homeFlowTaskExecBo.getTaskCode();
        boolean debugFlag = Objects.equals(homeFlowTaskExecBo.getDebugFlag(), SwitchEnum.TRUE.getCode());
        HomeFlowTaskLog homeFlowTaskLog = new HomeFlowTaskLog();
        Long userId = SecurityUtils.getUserId();
        homeFlowTaskLog.setCreateUserId(userId);
        homeFlowTaskLog.setCreateTime(new Date());
        homeFlowTaskLog.setTaskCode(taskCode);
        homeFlowTaskLogService.save(homeFlowTaskLog);
        String id = homeFlowTaskLog.getId();
        homeFlowTaskLog.setExecId(id);

        String redisKeyFlowExecTask = homeFlowTaskStepService.getRedisKeyFlowExecTask(taskCode);
        HomeFlowTaskExecTaskLogVo taskLog = homeFlowTaskExecBo.getTaskLog();
        taskLog.setTaskCode(taskCode);
        taskLog.setExecId(id);
        taskLog.setStartTime(new Date());
        if (debugFlag) {
            redisTemplate.opsForValue().set(redisKeyFlowExecTask, JSONUtil.toJsonStr(taskLog), 1, TimeUnit.DAYS);
        }
        Map<String, Object> paramMap;
        List<HomeFlowTaskVarBo> globalVarList;
        List<HomeFlowTaskVar> homeFlowTaskVarList;
        try {
            HomeFlowTask homeFlowTask = this.getByTaskCode(taskCode);
            if (Objects.isNull(homeFlowTask)) {
                throw new ServiceException("任务不存在，taskCode=" + taskCode);
            }
            taskLog.setTaskName(homeFlowTask.getTaskName());
            homeFlowTaskVarList = homeFlowTaskVarService.listByTaskCode(taskCode);
            List<HomeFlowTaskVarBo> homeFlowTaskVarBoList = BeanConvertUtils.convertList(homeFlowTaskVarList, HomeFlowTaskVarBo.class);
            globalVarList = homeFlowTaskVarBoList.stream()
                    .filter(o -> {
                        if (debugFlag) {
                            return Objects.equals(o.getIsUsed(), SwitchEnum.TRUE.getCode());
                        } else {
                            return Objects.equals(o.getGlobalFlag(), SwitchEnum.TRUE.getCode()) && Objects.equals(o.getIsUsed(), SwitchEnum.TRUE.getCode());
                        }
                    })
                    .collect(Collectors.toList());
            for (HomeFlowTaskVarBo homeFlowTaskVarBo : globalVarList) {
                Object object = homeFlowTaskExecBo.getParamMap().get(homeFlowTaskVarBo.getVarCodeFull());
                if (object instanceof String) {
                    homeFlowTaskVarBo.setVarValue(VelocityUtils.processTemplate((String) object, homeFlowTaskExecBo.getParamMap(), false).getTemplate());
                } else {
                    homeFlowTaskVarBo.setVarValue(object);
                }
            }
            paramMap = this.getVarMap(globalVarList);
            List<HomeFlowTaskVar> taskVarList = homeFlowTaskVarList.stream().filter(o -> Objects.equals(o.getFlowFlag(), SwitchEnum.TRUE.getCode())).collect(Collectors.toList());
            Map<String, Object> taskReqParamMap = new HashMap<>();
            for (HomeFlowTaskVar homeFlowTaskVar : taskVarList) {
                String varCodeFull = BeanConvertUtils.convert(homeFlowTaskVar, HomeFlowTaskVarBo.class).getVarCodeFull();
                taskReqParamMap.put(varCodeFull, paramMap.get(varCodeFull));
            }
            if (debugFlag) {
                taskLog.setReqParamMap(taskReqParamMap);
                redisTemplate.opsForValue().set(redisKeyFlowExecTask, JSONUtil.toJsonStr(taskLog), 1, TimeUnit.DAYS);
            }
        } catch (Exception e) {
            log.error("任务{}参数解析失败", taskCode, e);
            homeFlowTaskLog.setSuccessFlag(SwitchEnum.FALSE.getCode());
            homeFlowTaskLog.setErrorMsg(e.getMessage());
            taskLog.setErrorMsg(e.getMessage());
            try {
                homeFlowTaskLogService.updateById(homeFlowTaskLog);
            } catch (Exception e1) {
                log.error("任务{}日志保存失败", taskCode, e1);
            }
            throw new ServiceException("任务参数解析失败");
        }
        try {
            List<HomeFlowTaskStep> homeFlowTaskStepList = homeFlowTaskStepService.listByTaskCode(taskCode);
            Object result = null;
            for (int i = 1; i <= homeFlowTaskStepList.size(); i++) {
                long stepStartTime = System.currentTimeMillis();
                HomeFlowTaskStep homeFlowTaskStep = homeFlowTaskStepList.get(i - 1);
                if (Objects.equals(homeFlowTaskStep.getInteractionType(), HomeFlowTaskStepBo.InteractionTypeEnum.THIRD_CALL_US_API.getCode())) {
                    continue;
                }
                String stepCode = homeFlowTaskStep.getStepCode();
                HomeFlowTaskLog homeFlowTaskStepLog = new HomeFlowTaskLog();
                homeFlowTaskStepLog.setCreateUserId(userId);
                homeFlowTaskStepLog.setCreateTime(new Date());
                homeFlowTaskStepLog.setTaskCode(taskCode);
                homeFlowTaskStepLog.setStepCode(stepCode);
                homeFlowTaskStepLog.setExecId(id);
                HomeFlowTaskStepExecBo homeFlowTaskStepExecBo = new HomeFlowTaskStepExecBo();
                homeFlowTaskStepExecBo.setDebugFlag(homeFlowTaskExecBo.getDebugFlag());
                HomeFlowTaskExecTaskStepLogVo stepLog = homeFlowTaskStepExecBo.getStepLog();
                if (debugFlag) {
                    taskLog.getStepLogList().add(stepLog);
                    stepLog.setStepCode(stepCode);
                    stepLog.setStepName(homeFlowTaskStep.getStepName());
                    stepLog.setInteractionType(homeFlowTaskStep.getInteractionType());
                }
                try {
                    // 入参
                    Set<String> varCodeSet = new HashSet<>(VelocityUtils.getVarCodeList(
                            homeFlowTaskStep.getReqHeader() +
                                    homeFlowTaskStep.getReqForm() +
                                    homeFlowTaskStep.getReqTemplate() +
                                    homeFlowTaskStep.getReqBody()
                    ));
                    Map<String, Object> stepReqParamMap = new HashMap<>();
                    for (String key : varCodeSet) {
                        if (paramMap.containsKey(key)) {
                            Object object = paramMap.get(key);
                            stepReqParamMap.put(key, object);
                        }
                    }

                    // 执行
                    homeFlowTaskStepExecBo.setParamMap(paramMap);
                    HomeFlowTaskStepBo homeFlowTaskStepBo = BeanConvertUtils.convert(homeFlowTaskStep, HomeFlowTaskStepBo.class);
                    homeFlowTaskStepExecBo.setHomeFlowTaskStepBo(homeFlowTaskStepBo);
                    if (debugFlag) {
                        stepLog.setReqParamMap(stepReqParamMap);
                        redisTemplate.opsForValue().set(redisKeyFlowExecTask, JSONUtil.toJsonStr(taskLog), 1, TimeUnit.DAYS);
                    }
                    Object object = homeFlowTaskStepService.execTaskStep(homeFlowTaskStepExecBo);
                    result = object;
                    // 解析结果并存入全局变量
                    if (Objects.nonNull(object) && ObjectUtils.isNotEmpty(homeFlowTaskStepBo.getRespDataType())) {
                        HomeFlowTaskStepBo.RespDataTypeEnum respDataTypeEnum = HomeFlowTaskStepBo.RespDataTypeEnum.getEnumByCode(homeFlowTaskStepBo.getRespDataType());
                        List<HomeFlowTaskVarBo> taskVarList = globalVarList.stream().filter(o -> Objects.equals(o.getStepCode(), stepCode)).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(taskVarList)) {
                            for (HomeFlowTaskVarBo homeFlowTaskVarBo : taskVarList) {
                                try {
                                    Object value = null;
                                    HomeFlowTaskVarBo.DataTypeEnum dataTypeEnum = HomeFlowTaskVarBo.DataTypeEnum.getEnumByCode(homeFlowTaskVarBo.getDataType());
                                    String key = homeFlowTaskVarBo.getVarCodeFull();
                                    String varPath = homeFlowTaskVarBo.getVarPath();
                                    if (ObjectUtils.isEmpty(varPath)) {
                                        value = object;
                                    } else {
                                        switch (respDataTypeEnum) {
                                            case SINGLE: {
                                                if (dataTypeEnum == HomeFlowTaskVarBo.DataTypeEnum.SINGLE) {
                                                    value = object;
                                                } else {
                                                    throw new ServiceException("参数数据类型与响应数据类型不一致");
                                                }
                                            }
                                            break;
                                            case OBJECT: {
                                                if (ObjectUtils.isEmpty(varPath)) {
                                                    value = object;
                                                } else {
                                                    JSONObject jsonObject = JSONUtil.parseObj(object);
                                                /*
                                                switch (dataTypeEnum) {
                                                    case SINGLE: {
                                                        List<String> varCodeList = VelocityUtils.getVarCodeList(varPath);
                                                        if (CollectionUtils.isNotEmpty(varCodeList)) {
                                                            Map<String, Object> map = new HashMap<>();
                                                            for (String path : varCodeList) {
                                                                Object byPath = jsonObject.getByPath(path);
                                                                if (Objects.isNull(byPath)) {
                                                                    byPath = "";
                                                                }
                                                                map.put(path, byPath);
                                                                //  varPath = varPath.replace("${" + path + "}", String.valueOf(byPath));
                                                            }
                                                            value = VelocityUtils.processTemplate(varPath, map, false).getTemplate();
                                                        } else {
                                                            Object byPath = jsonObject.getByPath(varPath);
                                                            if (byPath instanceof JSONArray) {
                                                                JSONArray byPath1 = (JSONArray) byPath;
                                                                if (ObjectUtils.isNotEmpty(byPath1) && !byPath1.isEmpty()) {
                                                                    value = byPath1.get(0);
                                                                }
                                                            } else {
                                                                value = byPath;
                                                            }
                                                        }
                                                    }
                                                    break;
                                                    case OBJECT:
                                                    case COLLECTION: {
                                                        Object byPath = jsonObject.getByPath(varPath);
                                                        if (Objects.nonNull(byPath)) {
                                                            value = byPath;
                                                        }
                                                    }
                                                    break;
                                                }
                                                */
                                                    Object byPath = JSONUtil.getByPath(jsonObject, varPath);
                                                    if (Objects.nonNull(byPath)) {
                                                        value = byPath;
                                                    }
                                                }
                                            }
                                            break;
                                            case COLLECTION: {
                                                JSONArray jsonArray = JSONUtil.parseArray(object);
                                                switch (dataTypeEnum) {
                                                    case SINGLE: {
                                                        Object object1 = jsonArray.get(0);
                                                        if (Objects.nonNull(object1)) {
                                                            value = object1;
                                                        }
                                                    }
                                                    break;
                                                    case OBJECT: {
                                                        JSONObject jsonObject = JSONUtil.parseObj(jsonArray.get(0));
                                                        if (!jsonObject.isEmpty()) {
                                                            value = jsonObject;
                                                        }
                                                    }
                                                    break;
                                                    case COLLECTION: {
                                                        if (!jsonArray.isEmpty()) {
                                                            value = jsonArray;
                                                        }
                                                    }
                                                    break;
                                                }
                                            }
                                            break;
                                            case JSON: {
                                                String jsonStr = JSONUtil.toJsonStr(object).trim();
                                                if (jsonStr.startsWith("<") && jsonStr.endsWith(">")) {
                                                    value = JSONUtil.xmlToJson(jsonStr);
                                                } else if (jsonStr.startsWith("[") && jsonStr.endsWith("]")) {
                                                    value = JSONUtil.parseArray(jsonStr);
                                                } else if (jsonStr.startsWith("{") && jsonStr.endsWith("}")) {
                                                    value = JSONUtil.parseObj(jsonStr);
                                                } else {
                                                    value = object;
                                                }
                                                if (ObjectUtils.isNotEmpty(varPath)) {
                                                    value = JSONUtil.getByPath(JSONUtil.parseObj(value), varPath);
                                                }
                                            }
                                            break;
                                        }
                                    }
                                    if (Objects.nonNull(value)) {
                                        paramMap.put(key, value);
                                    } else {
                                        homeFlowTaskVarBo.setVarValue(homeFlowTaskVarBo.getDefaultValue());
                                        Map<String, Object> varMap = this.getVarMap(Collections.singletonList(homeFlowTaskVarBo));
                                        if (!varMap.isEmpty()) {
                                            paramMap.putAll(varMap);
                                        }
                                    }
                                } catch (Exception e) {
                                    log.error("参数解析结果失败：{}；{}", object, homeFlowTaskVarBo, e);
                                    throw new ServiceException("参数解析结果失败：" + JSONUtil.toJsonStr(object) + "；" + JSONUtil.toJsonStr(homeFlowTaskVarBo));
                                }
                            }
                        }
                    }
                    // 出参
                    List<HomeFlowTaskVar> respHomeFlowTaskVarList = homeFlowTaskVarList.stream()
                            .filter(o -> Objects.equals(o.getStepCode(), homeFlowTaskStep.getStepCode()))
                            .filter(o -> Objects.equals(o.getManualFlag(), SwitchEnum.FALSE.getCode()))
                            .collect(Collectors.toList());
                    HashMap<String, Object> respParamMap = new HashMap<>();
                    for (HomeFlowTaskVar homeFlowTaskVar : respHomeFlowTaskVarList) {
                        String varCodeFull = BeanConvertUtils.convert(homeFlowTaskVar, HomeFlowTaskVarBo.class).getVarCodeFull();
                        Object obj = paramMap.get(varCodeFull);
                        if (ObjectUtils.isNotEmpty(obj)) {
                            respParamMap.put(varCodeFull, paramMap.get(varCodeFull));
                        }
                    }
                    taskLog.setProcessPercent(i * 100 / homeFlowTaskStepList.size() + "%");
                    stepLog.setSuccessFlag(true);
                    if (debugFlag) {
                        stepLog.setRespParamMap(respParamMap);
                        redisTemplate.opsForValue().set(redisKeyFlowExecTask, JSONUtil.toJsonStr(taskLog), 1, TimeUnit.DAYS);
                    }
                    homeFlowTaskStepLog.setSuccessFlag(SwitchEnum.TRUE.getCode());
                } catch (Exception e) {
                    log.error("任务{}步骤{}执行失败", taskCode, stepCode, e);
                    stepLog.setErrorMsg(e.getMessage());
                    homeFlowTaskStepLog.setSuccessFlag(SwitchEnum.FALSE.getCode());
                    throw new ServiceException(stepLog.getErrorMsg());
                } finally {
                    try {
                        stepLog.setFinishFlag(true);
                        homeFlowTaskStepLog.setExecTime((System.currentTimeMillis() - stepStartTime) + "ms");
                        if (!stepLog.getSuccessFlag()) {
                            homeFlowTaskStepLog.setErrorMsg(JSONUtil.toJsonStr(stepLog));
                        }
                        homeFlowTaskLogService.save(homeFlowTaskStepLog);
                    } catch (Exception e) {
                        log.error("任务{}步骤{}日志保存失败：{}", taskCode, stepCode, stepLog, e);
                    }
                }
            }
            homeFlowTaskLog.setSuccessFlag(SwitchEnum.TRUE.getCode());
            taskLog.setSuccessFlag(true);
            if (debugFlag) {
                taskLog.setResult(result);
            }
            return result;
        } catch (Exception e) {
            log.error("任务{}执行失败", taskCode, e);
            homeFlowTaskLog.setSuccessFlag(SwitchEnum.FALSE.getCode());
            taskLog.setErrorMsg(e.getMessage());
            throw new ServiceException("任务执行失败");
        } finally {
            homeFlowTaskLog.setExecTime((System.currentTimeMillis() - taskStartTime) + "ms");
            try {
                homeFlowTaskLogService.updateById(homeFlowTaskLog);
            } catch (Exception e) {
                log.error("任务{}日志保存失败", taskCode, e);
            }
            taskLog.setFinishFlag(true);
            taskLog.setEndTime(new Date());
            if (debugFlag) {
                redisTemplate.opsForValue().set(redisKeyFlowExecTask, JSONUtil.toJsonStr(taskLog), 1, TimeUnit.DAYS);
            }
        }
    }

    private Map<String, Object> getVarMap(List<HomeFlowTaskVarBo> homeFlowTaskVarBoList) {
        Map<String, Object> paramMap = new HashMap<>();
        for (HomeFlowTaskVarBo homeFlowTaskVarBo : homeFlowTaskVarBoList) {
            HomeFlowTaskVarBo.DataTypeEnum dataTypeEnum = HomeFlowTaskVarBo.DataTypeEnum.getEnumByCode(homeFlowTaskVarBo.getDataType());
            String key = homeFlowTaskVarBo.getVarCodeFull();
            VelocityUtils.checkVarNameAvailable(Collections.singletonList(key));
            Object varValue = homeFlowTaskVarBo.getVarValue();
            if (ObjectUtils.isEmpty(varValue)) {
                varValue = VelocityUtils.processTemplate(homeFlowTaskVarBo.getDefaultValue(), paramMap, false).getTemplate();
            }
            if (ObjectUtils.isEmpty(varValue)) {
                varValue = null;
            } else {
                try {
                    switch (dataTypeEnum) {
                        case SINGLE:
                            break;
                        case COLLECTION:
                            JSONArray jsonArray = JSONUtil.parseArray(varValue);
                            varValue = JSONUtil.parseArray(jsonArray);
                            break;
                        case OBJECT:
                            varValue = JSONUtil.parseObj(varValue);
                            break;
                        case DATE:
                            if (!(varValue instanceof Date)) {
                                varValue = new SimpleDateFormat(DateUtil.FORMATER_3).parse(String.valueOf(varValue));
                            }
                            break;
                    }
                } catch (Exception e) {
                    throw new ServiceException(homeFlowTaskVarBo.getVarCodeFull() + "格式错误");
                }
            }
            paramMap.put(key, varValue);
        }
        return paramMap;
    }
}

